<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>snake learning</title>
	<style type="text/css">
		body{
			text-align: center;
		}
		#grass{
			border: solid 1px lightgray;
			width: auto;
			height: auto;
			position: absolute;
			left: 50%;
			margin-left: -250px;
			top: 50%;
			margin-top: -250px;
		}
		#grass table{
			border: 1px lightgray solid;
			width: 100%;
			height: 100%;
			border-collapse: collapse;
		}
		#grass table td{
			height: 30px;
			width: 30px;
			border: solid 1px lightgray;
			text-align: center;
			font-size: 10px;
			color: lightgray;
		}
		#snack_head{
			background-color: gold;
		}
		.snack_block{
			background-color: black;
			color: white;
		}
		.snack_food{
			background-color: lightgreen;
			color:white;
		}
	</style>
</head>
<body>
	<h4 id="score"></h4>
	<div id="grass"></div>



<script type="text/javascript">
	var TAB_W = 15;//表 列
	var TAB_H = 15;//表 行
	var TAB_BODY = multiArray(TAB_W,TAB_H);;//表格对象
	var food = [];//蛇 食物
	var snake = [];//蛇 节点坐标
	var aliveSnake = [];//行走中的蛇
	var SNAKE_LEN = 3;//蛇 长度
	var DIRECTION = 39;//运动方向 【默认:右】 37：左，38：上，39：右，40：下。
	var MOVE_CLOCK;//运行时钟
	var MOVE_SPEED=2;//速度
	//开始游戏
	(function(){
		renderTable();

		initSnake();
		document.getElementById('score').innerHTML = aliveSnake.length;

		renderFoodOnTable();

		renderSnakeOnTable();

		//switchClock(goRight);

		document.onkeydown = updateDirection; //绑定方向事件  

	})();


	//初始化蛇
	function initSnake(){
		snake = new Array();
		var pos = getRandNum(3,8);
		for (var i = 0; i < SNAKE_LEN; i++) {
			var x = pos[0];
			var y = pos[1]-i;
			snake.push([x,y]);
		}
		aliveSnake = snake;
		console.log('蛇：',aliveSnake);
		console.log('蛇头：',aliveSnake[0][0],',',aliveSnake[0][1]);
	}


	// 生成表格
	function  renderTable(){
		var tb = document.createElement('table');
		var tbody = document.createElement("tbody")  
		for(var i = 0; i< TAB_H; i++){
			var row = document.createElement("tr");//生成 行
			for (var j = 0; j < TAB_W; j++) {
				var col = document.createElement("td");//生成 列
				col.innerHTML=i+','+j;
				TAB_BODY[i][j] = col;
				row.appendChild(col);
			}
			tbody.appendChild(row);
		}
		tb.appendChild(tbody);
		document.getElementById('grass').appendChild(tb);
		console.log(TAB_BODY);
	}


	//将活动的蛇渲染在表格上
	function renderSnakeOnTable(){ 
		for (var i = 0; i < aliveSnake.length; i++) { 
			var sn_x = aliveSnake[i][0];
			var sn_y = aliveSnake[i][1]; 
			//如果是蛇头
			if(i==0){ 
				TAB_BODY[sn_x][sn_y].id  = 'snack_head';
			}else{
				TAB_BODY[sn_x][sn_y].className  = 'snack_block';
			}
			console.log(TAB_BODY[sn_x][sn_y]);
		}
	}

	//将食物渲染在表格上
	function renderFoodOnTable(){
		var pos = getRandNum(3,8);
		//如果食物和蛇节点不重合
		if(is_inArray(aliveSnake,pos)){
			food[0] = pos[0];
			food[1] = pos[1];
			TAB_BODY[food[0]][food[1]].className  = 'snack_food'; 
		}else{
			renderFoodOnTable();
		}
	}

	//更新移动方向
	function updateDirection(e){
		e = e || event;
		//console.log(e.which);
		if (Math.abs(e.which-DIRECTION)==2) {
			DIRECTION = DIRECTION;
			return false;
		}
		//DIRECTION = Math.abs(e.which-DIRECTION)==2?DIRECTION:e.which;
		DIRECTION = e.which;
		switch(DIRECTION){
			case 37:switchClock(goLeft);
					break;
			case 38:switchClock(goUp);
					break;
			case 39:switchClock(goRight);
					break;
			case 40:switchClock(goDown);
					break;
		}
	}

	//向左移动 添头去尾
	function goLeft(){ 
		var newHeadY = aliveSnake[0][1] ;
		var newHeadX = aliveSnake[0][0] ;
		console.log(newHeadX,newHeadY);
		newHeadY -= 1; 
		growupByEat();
		updateSnake(newHeadX,newHeadY);
	}

	//向右移动 添头去尾
	function goRight(){ 
		var newHeadY = aliveSnake[0][1] ;
		var newHeadX = aliveSnake[0][0] ;
		newHeadY += 1; 
		growupByEat();
		updateSnake(newHeadX,newHeadY);
	}

	//向上移动 添头去尾
	function goUp(){ 
		var newHeadX = aliveSnake[0][0];
		var newHeadY = aliveSnake[0][1];
		newHeadX -= 1; 
		growupByEat();
		updateSnake(newHeadX,newHeadY);
	}

	//向下移动 添头去尾
	function goDown(){ 
		var newHeadX = aliveSnake[0][0];
		var newHeadY = aliveSnake[0][1];
		newHeadX += 1; 
		growupByEat();
		updateSnake(newHeadX,newHeadY);
	}

	//添头去尾(更新头部，然后取出snake尾部，最后再重新生成 aliveSnake)
	function updateSnake(newHeadX,newHeadY){  
		var newHeadPos=[];//新蛇头坐标
		newHeadPos[0] = newHeadX;
		newHeadPos[1] = newHeadY;
		if(!is_inArray(aliveSnake.slice(4),newHeadPos)){
			gameover('你吃掉了自己的身体!');
			console.log('你吃掉了自己的身体');
			aliveSnake.pop();
			snake = aliveSnake;
		}
		isDeadYou(newHeadPos);
		console.log('new header:',newHeadPos);
		aliveSnake = [];//* 每次更新前 清空
		aliveSnake.push(newHeadPos);
		for (var i = 0; i < snake.length-1; i++) {
			aliveSnake.push(snake[i]);
		}
		snake = aliveSnake;//* 每次更新后 重新为snake赋值
		for (var i = 0; i < aliveSnake.length; i++) { 
		    console.log('aliveSnake[i]:',aliveSnake[i]);
		}
		clearClass('snack_block');
		renderSnakeOnTable();
 
	}

	//切换定时器
	function switchClock(func){
		func();
		clearInterval(MOVE_CLOCK);
		MOVE_CLOCK = setInterval(func,1000/MOVE_SPEED);
	}

	//吃到食物变长
	function growupByEat(){
		if(aliveSnake[0][0]==food[0]&&aliveSnake[0][1]==food[1]){ 
			console.log('食物:',food);
			// aliveSnake = [];//* 每次更新前 清空
			// aliveSnake.push(food);
			// for (var i = 0; i < snake.length; i++) {
			// 	aliveSnake.push(snake[i]);
			// }
			aliveSnake.push(food);
			snake = aliveSnake;//* 每次更新后 重新为snake赋值
			console.log('吃到食物后:',aliveSnake); 
			if(aliveSnake.length%5==0){
				MOVE_SPEED++;
			}
			document.getElementById('score').innerHTML = aliveSnake.length;
			renderFoodOnTable(); 
		}
	}
 
	//死亡宣判
	function isDeadYou(newHeadPos){
		if (newHeadPos[0]<0||newHeadPos[1]<0||newHeadPos[0]>TAB_W-1||newHeadPos[1]>TAB_H-1) {
			gameover();
		}
	}

	//gameover tip
	function gameover(msg){
		clearInterval(MOVE_CLOCK);
		var msg = msg||'触网死! replay?'
		if (confirm(msg)) {
			window.location.reload();
		} 
	}


	/**
	 * 通用函数
	 */

	//产生随机数
	function getRandNum(m,n){
		var x = Math.floor(Math.random()*(n - m)) + m; 
		var y = Math.floor(Math.random()*(n - m)) + m; 
		return [x,y];
	}

	//创建二维数组 
	function multiArray(m,n) {  
	    var arr =  new Array(n);  
	    for(var i=0; i<m; i++)   
	        arr[i] = new Array(m);  
	    return arr;  
	}  

	//判断某值(数组)是否存在于某二维数组
	function is_inArray(arr,val){
		console.log('arr:',arr,';val:',val);
		var len = arr.length;
		while(len--){ 
			if (arr[len][0]==val[0]&&arr[len][1]==val[1]) {
				console.log('重叠:',val);
				return false;
			}
		}
		return true;
	}

	//清除样式
	function clearClass(clsname){
		document.getElementById('snack_head').id='';
		var doms = document.getElementsByClassName(clsname);
		for (var i = 0; i < doms.length; i++) {
			doms[i].className="";
		}
	}

</script>
</body>
</html>